package com.milkshopbackend.milkshop.Service.impl;

import com.milkshopbackend.milkshop.Service.MailService;
import com.milkshopbackend.milkshop.Service.UserService;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.milkshopbackend.milkshop.entity.User;
import com.milkshopbackend.milkshop.entity.UserLoginDTO;
import com.milkshopbackend.milkshop.entity.UserRegisterDTO;
import com.milkshopbackend.milkshop.entity.UserProfileUpdateDTO;
import com.milkshopbackend.milkshop.entity.UserPasswordUpdateDTO;
import com.milkshopbackend.milkshop.entity.UserResetPasswordDTO;
import com.milkshopbackend.milkshop.mapper.UserMapper; // 假设 UserMapper 在 Mapper 包下
import com.milkshopbackend.milkshop.util.JWTUtil;
import com.milkshopbackend.milkshop.util.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.milkshopbackend.milkshop.util.CacheClient;
import com.milkshopbackend.milkshop.common.RedisConstants;
import javax.annotation.Resource;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.http.HttpServletRequest;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    @Qualifier("bCryptPasswordEncoder")
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private JWTUtil jwtUtil;

    @Autowired
    private MailService mailService;

    @Autowired
    private org.springframework.data.redis.core.StringRedisTemplate redisTemplate;

    @Resource
    private CacheClient cacheClient;

    @Autowired
    private HttpServletRequest request;

    @Value("${upload.path:D:/uploads/avatar}")
    private String uploadDir;

    @Transactional
    @Override
    public User register(UserRegisterDTO userRegisterDTO) {
        if (getUserByUsername(userRegisterDTO.getUsername()) != null) {
            throw new RuntimeException("用户名已存在");
        }

        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user);
        if (userRegisterDTO.getPassword() == null || userRegisterDTO.getPassword().trim().isEmpty()) {
            throw new RuntimeException("密码不能为空");
        }
        user.setPassword(passwordEncoder.encode(userRegisterDTO.getPassword()));
        user.setStatus(1);
        userMapper.insert(user);
        return user;
    }

    @Override
    public String login(UserLoginDTO loginDTO) {
        User user = getUserByUsername(loginDTO.getUsername());

        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        if (user.getStatus() != 1) {
            throw new RuntimeException("用户被禁用");
        }

        return jwtUtil.generateToken(user.getUsername(), user.getId());
    }

    @Override
    public User getUserByUsername(String username) {
        String key = RedisConstants.USER_INFO_KEY_PREFIX + "username:" + username;
        String json = redisTemplate.opsForValue().get(key);
        if (json != null) {
            User user = JSONUtil.toBean(json, User.class);
            if (user.getAvatar() != null && !user.getAvatar().startsWith("http")) {
                String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
                user.setAvatar(baseUrl + user.getAvatar());
            }
            return user;
        }
        LambdaQueryChainWrapper<User> wrapper = new LambdaQueryChainWrapper<>(userMapper);
        wrapper.eq(User::getUsername, username);
        User user = wrapper.one();
        if (user != null) {
            // 转换头像URL为完整路径
            if (user.getAvatar() != null && !user.getAvatar().startsWith("http")) {
                String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
                user.setAvatar(baseUrl + user.getAvatar());
            }
            // 缓存用户信息（注意：要缓存原始的相对路径）
            User cacheUser = new User();
            BeanUtils.copyProperties(user, cacheUser);
            if (cacheUser.getAvatar() != null && cacheUser.getAvatar().startsWith("http")) {
                cacheUser.setAvatar(cacheUser.getAvatar().substring(cacheUser.getAvatar().indexOf("/uploads")));
            }
            redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(cacheUser), RedisConstants.USER_INFO_TTL, java.util.concurrent.TimeUnit.SECONDS);
        }
        return user;
    }

    @Override
    public User getById(Long userId) {
        String key = RedisConstants.USER_INFO_KEY_PREFIX + userId;
        String json = redisTemplate.opsForValue().get(key);
        if (json != null) {
            User user = JSONUtil.toBean(json, User.class);
            if (user.getAvatar() != null && !user.getAvatar().startsWith("http")) {
                String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
                user.setAvatar(baseUrl + user.getAvatar());
            }
            return user;
        }
        User user = userMapper.selectById(userId);
        if (user != null) {
            // 转换头像URL为完整路径
            if (user.getAvatar() != null && !user.getAvatar().startsWith("http")) {
                String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
                user.setAvatar(baseUrl + user.getAvatar());
            }
            // 缓存用户信息（注意：要缓存原始的相对路径）
            User cacheUser = new User();
            BeanUtils.copyProperties(user, cacheUser);
            if (cacheUser.getAvatar() != null && cacheUser.getAvatar().startsWith("http")) {
                cacheUser.setAvatar(cacheUser.getAvatar().substring(cacheUser.getAvatar().indexOf("/uploads")));
            }
            redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(cacheUser), RedisConstants.USER_INFO_TTL, java.util.concurrent.TimeUnit.SECONDS);
        }
        return user;
    }

    @Override
    public void updateProfile(UserProfileUpdateDTO profileDTO) {
        Long userId = SecurityUtils.getCurrentUserId();
        User user = userMapper.selectById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");
        if (profileDTO.getUsername() != null)
            user.setUsername(profileDTO.getUsername());
        if (profileDTO.getEmail() != null)
            user.setEmail(profileDTO.getEmail());
        if (profileDTO.getPhone() != null)
            user.setPhone(profileDTO.getPhone());
        userMapper.updateById(user);
        // 清理缓存
        redisTemplate.delete(RedisConstants.USER_INFO_KEY_PREFIX + userId);
        redisTemplate.delete(RedisConstants.USER_INFO_KEY_PREFIX + "username:" + user.getUsername());
    }

    @Override
    public String uploadAvatar(MultipartFile file) {
        if (file.isEmpty())
            throw new RuntimeException("文件为空");
        String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            boolean created = dir.mkdirs();
            if (!created) {
                throw new RuntimeException("上传目录创建失败: " + uploadDir);
            }
        }
        if (!dir.canWrite()) {
            throw new RuntimeException("上传目录不可写: " + uploadDir);
        }
        File dest = new File(dir, fileName);
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("上传失败: " + e.getMessage(), e);
        }
        String urlPath = "/uploads/avatar/" + fileName;
        String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
        String avatarUrl = baseUrl + urlPath;
        
        // 更新用户头像
        Long userId = SecurityUtils.getCurrentUserId();
        User user = userMapper.selectById(userId);
        user.setAvatar(urlPath); // 数据库中存储相对路径
        userMapper.updateById(user);
        
        // 清理缓存
        redisTemplate.delete(RedisConstants.USER_INFO_KEY_PREFIX + userId);
        redisTemplate.delete(RedisConstants.USER_INFO_KEY_PREFIX + "username:" + user.getUsername());
        
        return avatarUrl; // 返回完整URL
    }

    @Override
    public void updatePassword(UserPasswordUpdateDTO dto) {
        Long userId = SecurityUtils.getCurrentUserId();
        User user = userMapper.selectById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");
        if (!passwordEncoder.matches(dto.getOldPassword(), user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }
        user.setPassword(passwordEncoder.encode(dto.getNewPassword()));
        userMapper.updateById(user);
    }

    @Override
    public void sendResetCode(String email) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("email", email));
        if (user == null)
            throw new RuntimeException("邮箱未注册");
        String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        // 发送邮件（伪代码）
        mailService.send(email, "重置密码验证码", "您的验证码是：" + code);
        // 存储验证码到Redis，5分钟有效
        redisTemplate.opsForValue().set("reset:code:" + email, code, 5, java.util.concurrent.TimeUnit.MINUTES);
    }

    @Override
    public void resetPassword(UserResetPasswordDTO dto) {
        String cacheCode = redisTemplate.opsForValue().get("reset:code:" + dto.getEmail());
        if (cacheCode == null || !cacheCode.equals(dto.getCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("email", dto.getEmail()));
        if (user == null)
            throw new RuntimeException("用户不存在");
        user.setPassword(passwordEncoder.encode(dto.getNewPassword()));
        userMapper.updateById(user);
        // 删除验证码
        redisTemplate.delete("reset:code:" + dto.getEmail());
    }
}
